#include "VirtualDeviceConfigDialog.h"
#include "utils/CsvHelper.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QFormLayout>
#include <QGroupBox>
#include <QLabel>
#include <QMessageBox>
#include <QHeaderView>
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QDialogButtonBox>
#include <QJsonArray>
#include <QFileDialog>
#include <QMenu>
#include <QAction>

namespace ModbusPlexLink {

VirtualDeviceConfigDialog::VirtualDeviceConfigDialog(const QJsonObject& config, QWidget *parent)
    : QDialog(parent)
    , m_initialConfig(config)
    , m_isNewDevice(config.isEmpty())
    , m_isUpdatingTable(false)
{
    setupUi();
    loadConfig();
    
    resize(1000, 700);
}

VirtualDeviceConfigDialog::~VirtualDeviceConfigDialog() {
}

void VirtualDeviceConfigDialog::setupUi() {
    QVBoxLayout* mainLayout = new QVBoxLayout(this);
    
    // 基本信息部分
    QWidget* basicInfoWidget = createBasicInfoSection();
    mainLayout->addWidget(basicInfoWidget);
    
    // 映射表格部分
    QWidget* mappingWidget = createMappingTableSection();
    mainLayout->addWidget(mappingWidget, 1);
    
    // 对话框按钮
    QDialogButtonBox* buttonBox = new QDialogButtonBox(
        QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
    
    connect(buttonBox, &QDialogButtonBox::accepted, this, &VirtualDeviceConfigDialog::onAccepted);
    connect(buttonBox, &QDialogButtonBox::rejected, this, &VirtualDeviceConfigDialog::onRejected);
    
    mainLayout->addWidget(buttonBox);
    
    setLayout(mainLayout);
}

QWidget* VirtualDeviceConfigDialog::createBasicInfoSection() {
    QGroupBox* groupBox = new QGroupBox(tr("基本信息"), this);
    QFormLayout* formLayout = new QFormLayout(groupBox);
    
    // 设备名称
    m_nameEdit = new QLineEdit(groupBox);
    m_nameEdit->setPlaceholderText(tr("例如：电表1"));
    formLayout->addRow(tr("设备名称:"), m_nameEdit);
    
    // 虚拟从站ID
    m_virtualUnitIdSpin = new QSpinBox(groupBox);
    m_virtualUnitIdSpin->setRange(1, 247);
    m_virtualUnitIdSpin->setValue(1);
    formLayout->addRow(tr("虚拟从站ID:"), m_virtualUnitIdSpin);
    
    // 启用/禁用
    m_enabledCheck = new QCheckBox(tr("启用此虚拟设备"), groupBox);
    m_enabledCheck->setChecked(true);
    formLayout->addRow("", m_enabledCheck);
    
    groupBox->setLayout(formLayout);
    return groupBox;
}

QWidget* VirtualDeviceConfigDialog::createMappingTableSection() {
    QGroupBox* groupBox = new QGroupBox(tr("映射规则列表"), this);
    QVBoxLayout* layout = new QVBoxLayout(groupBox);
    
    // 映射表格
    m_mappingTable = new QTableWidget(groupBox);
    m_mappingTable->setColumnCount(10);
    m_mappingTable->setHorizontalHeaderLabels({
        tr("序号"), tr("标签名"), tr("功能码"), tr("寄存器地址"),
        tr("数据类型"), tr("字节序"), tr("倍率"), tr("偏移"),
        tr("可写"), tr("注释")
    });
    
    m_mappingTable->setSelectionBehavior(QAbstractItemView::SelectRows);
    m_mappingTable->setSelectionMode(QAbstractItemView::SingleSelection);
    m_mappingTable->setAlternatingRowColors(true);
    m_mappingTable->horizontalHeader()->setStretchLastSection(true);
    m_mappingTable->verticalHeader()->setVisible(false);
    
    m_mappingTable->setColumnWidth(0, 50);   // 序号
    m_mappingTable->setColumnWidth(1, 150);  // 标签名
    m_mappingTable->setColumnWidth(2, 80);   // 功能码
    m_mappingTable->setColumnWidth(3, 100);  // 地址
    m_mappingTable->setColumnWidth(4, 100);  // 数据类型
    m_mappingTable->setColumnWidth(5, 80);   // 字节序
    m_mappingTable->setColumnWidth(6, 70);   // 倍率
    m_mappingTable->setColumnWidth(7, 70);   // 偏移
    m_mappingTable->setColumnWidth(8, 60);   // 可写
    
    connect(m_mappingTable, &QTableWidget::itemSelectionChanged,
            this, &VirtualDeviceConfigDialog::onMappingTableSelectionChanged);
    connect(m_mappingTable, &QTableWidget::cellChanged,
            this, &VirtualDeviceConfigDialog::onMappingTableCellChanged);
    
    layout->addWidget(m_mappingTable);
    
    // 操作按钮
    QHBoxLayout* buttonLayout = new QHBoxLayout();
    
    m_addMappingBtn = new QPushButton(tr("添加映射"), groupBox);
    m_deleteMappingBtn = new QPushButton(tr("删除映射"), groupBox);
    m_duplicateMappingBtn = new QPushButton(tr("复制映射"), groupBox);
    m_importCsvBtn = new QPushButton(tr("从CSV导入..."), groupBox);
    m_exportCsvBtn = new QPushButton(tr("导出到CSV..."), groupBox);
    
    m_deleteMappingBtn->setEnabled(false);
    m_duplicateMappingBtn->setEnabled(false);
    m_exportCsvBtn->setEnabled(false); // 后续阶段实现
    
    connect(m_addMappingBtn, &QPushButton::clicked,
            this, &VirtualDeviceConfigDialog::onAddMapping);
    connect(m_deleteMappingBtn, &QPushButton::clicked,
            this, &VirtualDeviceConfigDialog::onDeleteMapping);
    connect(m_duplicateMappingBtn, &QPushButton::clicked,
            this, &VirtualDeviceConfigDialog::onDuplicateMapping);
    connect(m_importCsvBtn, &QPushButton::clicked,
            this, &VirtualDeviceConfigDialog::onImportCsv);
    connect(m_exportCsvBtn, &QPushButton::clicked,
            this, &VirtualDeviceConfigDialog::onExportCsv);
    
    buttonLayout->addWidget(m_addMappingBtn);
    buttonLayout->addWidget(m_deleteMappingBtn);
    buttonLayout->addWidget(m_duplicateMappingBtn);
    buttonLayout->addSpacing(20);
    buttonLayout->addWidget(m_importCsvBtn);
    buttonLayout->addWidget(m_exportCsvBtn);
    buttonLayout->addStretch();
    
    layout->addLayout(buttonLayout);
    
    groupBox->setLayout(layout);
    return groupBox;
}

void VirtualDeviceConfigDialog::loadConfig() {
    if (m_initialConfig.isEmpty()) {
        return;
    }
    
    // 加载基本信息
    m_nameEdit->setText(m_initialConfig.value("name").toString());
    m_virtualUnitIdSpin->setValue(m_initialConfig.value("virtualUnitId").toInt(1));
    m_enabledCheck->setChecked(m_initialConfig.value("enabled").toBool(true));
    
    // 加载映射规则
    QJsonArray mappingsArray = m_initialConfig.value("mappings").toArray();
    for (const QJsonValue& value : mappingsArray) {
        if (value.isObject()) {
            QJsonObject mappingObj = value.toObject();
            ServerMappingRule rule;
            rule.tagName = mappingObj.value("tagName").toString();
            rule.comment = mappingObj.value("comment").toString();
            rule.address = mappingObj.value("address").toInt();
            rule.scale = mappingObj.value("scale").toDouble(1.0);
            rule.offset = mappingObj.value("offset").toDouble(0.0);
            rule.writable = mappingObj.value("writable").toBool(false);
            rule.accessLevel = mappingObj.value("accessLevel").toString();
            
            // 支持字符串和整数两种格式（兼容性）
            QJsonValue regTypeValue = mappingObj.value("registerType");
            if (regTypeValue.isString()) {
                rule.registerType = DataTypeUtils::registerTypeFromString(regTypeValue.toString());
            } else {
                rule.registerType = static_cast<RegisterType>(regTypeValue.toInt());
            }
            
            QJsonValue dataTypeValue = mappingObj.value("dataType");
            if (dataTypeValue.isString()) {
                rule.dataType = DataTypeUtils::dataTypeFromString(dataTypeValue.toString());
            } else {
                rule.dataType = static_cast<DataType>(dataTypeValue.toInt());
            }
            
            QJsonValue byteOrderValue = mappingObj.value("byteOrder");
            if (byteOrderValue.isString()) {
                rule.byteOrder = DataTypeUtils::byteOrderFromString(byteOrderValue.toString());
            } else {
                rule.byteOrder = static_cast<ByteOrder>(byteOrderValue.toInt());
            }
            
            m_mappings.append(rule);
        }
    }
    
    refreshMappingTable();
}

bool VirtualDeviceConfigDialog::validateConfig() {
    // 验证设备名称
    if (m_nameEdit->text().trimmed().isEmpty()) {
        QMessageBox::warning(this, tr("验证失败"), tr("请输入设备名称"));
        m_nameEdit->setFocus();
        return false;
    }
    
    // 验证映射规则
    if (m_mappings.isEmpty()) {
        QMessageBox::warning(this, tr("验证失败"), 
            tr("至少需要添加一个映射规则\n\n提示：点击\"添加映射\"按钮创建映射"));
        return false;
    }
    
    // 检查地址是否重复
    QMap<int, QString> addressMap;
    for (const ServerMappingRule& rule : m_mappings) {
        int registerCount = DataTypeUtils::getRegisterCount(rule.dataType);
        for (int i = 0; i < registerCount; ++i) {
            int addr = rule.address + i;
            if (addressMap.contains(addr)) {
                QMessageBox::warning(this, tr("验证失败"),
                    tr("地址 %1 重复\n\n标签 '%2' 和 '%3' 的地址范围重叠")
                    .arg(addr).arg(addressMap[addr]).arg(rule.tagName));
                return false;
            }
            addressMap[addr] = rule.tagName;
        }
    }
    
    return true;
}

QJsonObject VirtualDeviceConfigDialog::getConfig() const {
    QJsonObject config;
    config["name"] = m_nameEdit->text().trimmed();
    config["virtualUnitId"] = m_virtualUnitIdSpin->value();
    config["enabled"] = m_enabledCheck->isChecked();
    
    QJsonArray mappingsArray;
    for (const ServerMappingRule& rule : m_mappings) {
        QJsonObject mappingObj;
        mappingObj["tagName"] = rule.tagName;
        mappingObj["comment"] = rule.comment;
        mappingObj["registerType"] = DataTypeUtils::registerTypeToString(rule.registerType);
        mappingObj["address"] = rule.address;
        mappingObj["dataType"] = DataTypeUtils::dataTypeToString(rule.dataType);
        mappingObj["byteOrder"] = DataTypeUtils::byteOrderToString(rule.byteOrder);
        mappingObj["scale"] = rule.scale;
        mappingObj["offset"] = rule.offset;
        mappingObj["writable"] = rule.writable;
        mappingObj["accessLevel"] = rule.accessLevel;
        
        mappingsArray.append(mappingObj);
    }
    config["mappings"] = mappingsArray;
    
    return config;
}

void VirtualDeviceConfigDialog::refreshMappingTable() {
    m_isUpdatingTable = true;
    
    m_mappingTable->setRowCount(m_mappings.size());
    
    for (int i = 0; i < m_mappings.size(); ++i) {
        setupMappingTableRow(i, m_mappings[i]);
    }
    
    m_isUpdatingTable = false;
    updateMappingButtons();
}

void VirtualDeviceConfigDialog::setupMappingTableRow(int row, const ServerMappingRule& rule) {
    // 序号（只读）
    QTableWidgetItem* rowNumItem = new QTableWidgetItem(QString::number(row + 1));
    rowNumItem->setTextAlignment(Qt::AlignCenter);
    rowNumItem->setFlags(rowNumItem->flags() & ~Qt::ItemIsEditable);
    rowNumItem->setBackground(QBrush(QColor(240, 240, 240)));
    m_mappingTable->setItem(row, 0, rowNumItem);
    
    // 标签名（可编辑）
    QTableWidgetItem* tagNameItem = new QTableWidgetItem(rule.tagName);
    m_mappingTable->setItem(row, 1, tagNameItem);
    
    // 功能码（下拉框）
    QComboBox* registerTypeCombo = new QComboBox();
    registerTypeCombo->addItem("01 (Coil)", static_cast<int>(RegisterType::Coil));
    registerTypeCombo->addItem("02 (Discrete)", static_cast<int>(RegisterType::DiscreteInput));
    registerTypeCombo->addItem("03 (Holding)", static_cast<int>(RegisterType::HoldingRegister));
    registerTypeCombo->addItem("04 (Input)", static_cast<int>(RegisterType::InputRegister));
    registerTypeCombo->setCurrentIndex(registerTypeCombo->findData(static_cast<int>(rule.registerType)));
    m_mappingTable->setCellWidget(row, 2, registerTypeCombo);
    
    // 地址（可编辑）
    QTableWidgetItem* addressItem = new QTableWidgetItem(QString::number(rule.address));
    addressItem->setTextAlignment(Qt::AlignCenter);
    m_mappingTable->setItem(row, 3, addressItem);
    
    // 数据类型（下拉框）
    QComboBox* dataTypeCombo = new QComboBox();
    dataTypeCombo->addItem("UInt16", static_cast<int>(DataType::UInt16));
    dataTypeCombo->addItem("Int16", static_cast<int>(DataType::Int16));
    dataTypeCombo->addItem("UInt32", static_cast<int>(DataType::UInt32));
    dataTypeCombo->addItem("Int32", static_cast<int>(DataType::Int32));
    dataTypeCombo->addItem("Float32", static_cast<int>(DataType::Float32));
    dataTypeCombo->addItem("UInt64", static_cast<int>(DataType::UInt64));
    dataTypeCombo->addItem("Int64", static_cast<int>(DataType::Int64));
    dataTypeCombo->addItem("Float64", static_cast<int>(DataType::Float64));
    dataTypeCombo->setCurrentIndex(dataTypeCombo->findData(static_cast<int>(rule.dataType)));
    m_mappingTable->setCellWidget(row, 4, dataTypeCombo);
    
    // 字节序（下拉框）
    QComboBox* byteOrderCombo = new QComboBox();
    byteOrderCombo->addItem("AB", static_cast<int>(ByteOrder::AB));
    byteOrderCombo->addItem("BA", static_cast<int>(ByteOrder::BA));
    byteOrderCombo->addItem("ABCD", static_cast<int>(ByteOrder::ABCD));
    byteOrderCombo->addItem("DCBA", static_cast<int>(ByteOrder::DCBA));
    byteOrderCombo->addItem("BADC", static_cast<int>(ByteOrder::BADC));
    byteOrderCombo->addItem("CDAB", static_cast<int>(ByteOrder::CDAB));
    byteOrderCombo->setCurrentIndex(byteOrderCombo->findData(static_cast<int>(rule.byteOrder)));
    m_mappingTable->setCellWidget(row, 5, byteOrderCombo);
    
    // 倍率（可编辑）
    QTableWidgetItem* scaleItem = new QTableWidgetItem(QString::number(rule.scale, 'f', 3));
    scaleItem->setTextAlignment(Qt::AlignCenter);
    m_mappingTable->setItem(row, 6, scaleItem);
    
    // 偏移（可编辑）
    QTableWidgetItem* offsetItem = new QTableWidgetItem(QString::number(rule.offset, 'f', 3));
    offsetItem->setTextAlignment(Qt::AlignCenter);
    m_mappingTable->setItem(row, 7, offsetItem);
    
    // 可写（下拉框）
    QComboBox* writableCombo = new QComboBox();
    writableCombo->addItem(tr("否"), false);
    writableCombo->addItem(tr("是"), true);
    writableCombo->setCurrentIndex(rule.writable ? 1 : 0);
    m_mappingTable->setCellWidget(row, 8, writableCombo);
    
    // 注释（可编辑）
    QTableWidgetItem* commentItem = new QTableWidgetItem(rule.comment);
    m_mappingTable->setItem(row, 9, commentItem);
}

ServerMappingRule VirtualDeviceConfigDialog::getMappingRuleFromRow(int row) const {
    ServerMappingRule rule;
    
    if (row < 0 || row >= m_mappingTable->rowCount()) {
        return rule;
    }
    
    // 标签名
    QTableWidgetItem* tagNameItem = m_mappingTable->item(row, 1);
    rule.tagName = tagNameItem ? tagNameItem->text() : "";
    
    // 功能码
    QComboBox* registerTypeCombo = qobject_cast<QComboBox*>(m_mappingTable->cellWidget(row, 2));
    rule.registerType = registerTypeCombo ? 
        static_cast<RegisterType>(registerTypeCombo->currentData().toInt()) : 
        RegisterType::HoldingRegister;
    
    // 地址
    QTableWidgetItem* addressItem = m_mappingTable->item(row, 3);
    rule.address = addressItem ? addressItem->text().toInt() : 0;
    
    // 数据类型
    QComboBox* dataTypeCombo = qobject_cast<QComboBox*>(m_mappingTable->cellWidget(row, 4));
    rule.dataType = dataTypeCombo ? 
        static_cast<DataType>(dataTypeCombo->currentData().toInt()) : 
        DataType::UInt16;
    
    // 字节序
    QComboBox* byteOrderCombo = qobject_cast<QComboBox*>(m_mappingTable->cellWidget(row, 5));
    rule.byteOrder = byteOrderCombo ? 
        static_cast<ByteOrder>(byteOrderCombo->currentData().toInt()) : 
        ByteOrder::AB;
    
    // 倍率
    QTableWidgetItem* scaleItem = m_mappingTable->item(row, 6);
    rule.scale = scaleItem ? scaleItem->text().toDouble() : 1.0;
    
    // 偏移
    QTableWidgetItem* offsetItem = m_mappingTable->item(row, 7);
    rule.offset = offsetItem ? offsetItem->text().toDouble() : 0.0;
    
    // 可写
    QComboBox* writableCombo = qobject_cast<QComboBox*>(m_mappingTable->cellWidget(row, 8));
    rule.writable = writableCombo ? writableCombo->currentData().toBool() : false;
    
    // 注释
    QTableWidgetItem* commentItem = m_mappingTable->item(row, 9);
    rule.comment = commentItem ? commentItem->text() : "";
    
    return rule;
}

void VirtualDeviceConfigDialog::updateMappingButtons() {
    bool hasSelection = m_mappingTable->currentRow() >= 0;
    bool hasMappings = m_mappings.size() > 0;
    
    m_deleteMappingBtn->setEnabled(hasSelection);
    m_duplicateMappingBtn->setEnabled(hasSelection);
    m_exportCsvBtn->setEnabled(hasMappings);
}

void VirtualDeviceConfigDialog::onAddMapping() {
    ServerMappingRule rule;
    rule.tagName = tr("NewTag%1").arg(m_mappings.size() + 1);
    rule.registerType = RegisterType::HoldingRegister;
    rule.dataType = DataType::UInt16;
    rule.byteOrder = ByteOrder::AB;
    rule.scale = 1.0;
    rule.offset = 0.0;
    rule.writable = false;
    
    // 智能地址递增
    if (!m_mappings.isEmpty()) {
        const ServerMappingRule& lastRule = m_mappings.last();
        int lastRegisterCount = DataTypeUtils::getRegisterCount(lastRule.dataType);
        rule.address = lastRule.address + lastRegisterCount;
    } else {
        rule.address = 0;
    }
    
    m_mappings.append(rule);
    refreshMappingTable();
    m_mappingTable->selectRow(m_mappings.size() - 1);
    m_mappingTable->editItem(m_mappingTable->item(m_mappings.size() - 1, 1)); // 焦点在标签名
}

void VirtualDeviceConfigDialog::onDeleteMapping() {
    int row = m_mappingTable->currentRow();
    if (row < 0 || row >= m_mappings.size()) {
        return;
    }
    
    m_mappings.removeAt(row);
    refreshMappingTable();
    
    // 选中下一行或上一行
    if (row < m_mappings.size()) {
        m_mappingTable->selectRow(row);
    } else if (m_mappings.size() > 0) {
        m_mappingTable->selectRow(m_mappings.size() - 1);
    }
}

void VirtualDeviceConfigDialog::onDuplicateMapping() {
    int row = m_mappingTable->currentRow();
    if (row < 0 || row >= m_mappings.size()) {
        return;
    }
    
    // 先保存当前行的数据
    m_mappings[row] = getMappingRuleFromRow(row);
    
    // 复制映射规则
    ServerMappingRule rule = m_mappings[row];
    
    // 智能地址递增和标签命名
    int registerCount = DataTypeUtils::getRegisterCount(rule.dataType);
    rule.address += registerCount;
    rule.tagName += tr("_副本");
    
    m_mappings.insert(row + 1, rule);
    refreshMappingTable();
    m_mappingTable->selectRow(row + 1);
}

void VirtualDeviceConfigDialog::onImportCsv() {
    // 创建菜单选择导入方式
    QMenu menu(this);
    QAction* importAction = menu.addAction(tr("导入CSV文件"));
    QAction* templateAction = menu.addAction(tr("下载CSV模板"));
    
    QAction* selectedAction = menu.exec(QCursor::pos());
    
    if (selectedAction == templateAction) {
        // 生成CSV模板
        QString fileName = QFileDialog::getSaveFileName(
            this,
            tr("保存CSV模板"),
            "server_mapping_template.csv",
            tr("CSV文件 (*.csv)")
        );
        
        if (!fileName.isEmpty()) {
            if (CsvHelper::generateServerTemplate(fileName)) {
                QMessageBox::information(this, tr("成功"), 
                    tr("CSV模板已生成：\n%1\n\n请参考模板格式填写数据后导入。").arg(fileName));
            } else {
                QMessageBox::warning(this, tr("错误"), 
                    tr("无法生成CSV模板文件。"));
            }
        }
        return;
    }
    
    if (selectedAction == importAction) {
        // 导入CSV文件
        QString fileName = QFileDialog::getOpenFileName(
            this,
            tr("导入CSV文件"),
            "",
            tr("CSV文件 (*.csv)")
        );
        
        if (fileName.isEmpty()) {
            return;
        }
        
        // 询问是否清空现有数据
        QMessageBox::StandardButton reply = QMessageBox::question(
            this,
            tr("导入模式"),
            tr("是否清空现有映射规则？\n\n"
               "点击【是】：清空现有规则，只保留导入的数据\n"
               "点击【否】：追加导入的数据到现有规则"),
            QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel
        );
        
        if (reply == QMessageBox::Cancel) {
            return;
        }
        
        bool clearExisting = (reply == QMessageBox::Yes);
        
        // 导入CSV
        QList<ServerMappingRule> importedMappings;
        QString errorMsg;
        
        if (!CsvHelper::importServerMappings(fileName, importedMappings, errorMsg)) {
            QMessageBox::critical(this, tr("导入失败"), 
                tr("无法导入CSV文件：\n%1").arg(errorMsg));
            return;
        }
        
        // 更新映射列表
        if (clearExisting) {
            m_mappings.clear();
        }
        
        m_mappings.append(importedMappings);
        
        // 刷新表格
        refreshMappingTable();
        
        QMessageBox::information(this, tr("导入成功"), 
            tr("成功导入 %1 条映射规则。").arg(importedMappings.size()));
    }
}

void VirtualDeviceConfigDialog::onExportCsv() {
    if (m_mappings.isEmpty()) {
        QMessageBox::information(this, tr("提示"), 
            tr("当前没有映射规则可导出。"));
        return;
    }
    
    // 先同步表格数据到m_mappings
    for (int i = 0; i < m_mappingTable->rowCount(); ++i) {
        if (i < m_mappings.size()) {
            m_mappings[i] = getMappingRuleFromRow(i);
        }
    }
    
    QString fileName = QFileDialog::getSaveFileName(
        this,
        tr("导出到CSV"),
        QString("server_mappings_%1.csv").arg(m_nameEdit->text()),
        tr("CSV文件 (*.csv)")
    );
    
    if (fileName.isEmpty()) {
        return;
    }
    
    if (CsvHelper::exportServerMappings(m_mappings, fileName)) {
        QMessageBox::information(this, tr("导出成功"), 
            tr("成功导出 %1 条映射规则到：\n%2").arg(m_mappings.size()).arg(fileName));
    } else {
        QMessageBox::critical(this, tr("导出失败"), 
            tr("无法导出CSV文件。"));
    }
}

void VirtualDeviceConfigDialog::onMappingTableSelectionChanged() {
    updateMappingButtons();
}

void VirtualDeviceConfigDialog::onMappingTableCellChanged(int row, int column) {
    if (m_isUpdatingTable || row < 0 || row >= m_mappings.size()) {
        return;
    }
    
    // 保存表格中的修改到内部数据结构
    m_mappings[row] = getMappingRuleFromRow(row);
}

void VirtualDeviceConfigDialog::onAccepted() {
    // 在验证前，保存所有行的修改
    for (int i = 0; i < m_mappings.size(); ++i) {
        m_mappings[i] = getMappingRuleFromRow(i);
    }
    
    if (validateConfig()) {
        accept();
    }
}

void VirtualDeviceConfigDialog::onRejected() {
    reject();
}

} // namespace ModbusPlexLink

